package org.glassunit.core.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Frederic Müller
 */
public class FileUtils {

    /**
     * Copies the content of the input stream to the output stream.
     * Both input stream and output stream are kept open.
     * @param inputStream input stream
     * @param outputStream output stream
     * @throws IOException thrown on any transfer exception
     */
    public static void copyStream(final InputStream inputStream, final OutputStream outputStream) throws IOException {
        final byte buffer[] = new byte[1024];
        while (true) {
            final int size = inputStream.read(buffer, 0, buffer.length);
            if (size <= 0) {
                break;
            }
            outputStream.write(buffer, 0, size);
        }
    }

    /**
     * Copies the content of the input stream to the given file.
     * Both input stream and output stream are closed.
     * @param inputStream input stream
     * @param file output file
     * @throws IOException thrown on transfer errors
     */
    public static void saveFile(final InputStream inputStream, final File file) throws IOException {
        final FileOutputStream outputStream = new FileOutputStream(file);
        copyStream(inputStream, outputStream);
        inputStream.close();
        outputStream.close();
    }

    /**
     * Creates the given directory if needed.
     * If the given file is indeed a file it is deleted prior to creating the directory.
     * @param file file
     * @return directory
     */
    public static File createDirectory(final File file) {

        if (file != null) {
            if (file.exists() && !file.isDirectory() && !file.delete()) {
                throw new RuntimeException(String.format("Could not remove existing file %s", file.getAbsolutePath()));
            }
            if (!file.exists() && !file.mkdirs()) {
                throw new RuntimeException(String.format("Could not create directory %s", file.getAbsolutePath()));
            }
            return file;
        }
        throw new RuntimeException("No file given");
    }

    /**
     * Creates the given directory.
     * @param file directory
     * @return directory
     */
    public static File createFile(final File file) {
        try {
            file.createNewFile();
        } catch (final IOException ex) {
            Logger.getAnonymousLogger().log(Level.SEVERE, null, ex);
        }
        return file;
    }

    /**
     * Recursively delete directory or file.
     * @param file directory or file
     * @return deletion result
     */
    public static boolean deleteFileRecursive(final File file) {
        if (file.exists()) {
            if (file.isDirectory()) {
                for (File subFile : file.listFiles()) {
                    deleteFileRecursive(subFile);
                }
            }
            return file.delete();
        } else {
            return false;
        }
    }

    /**
     * Gets the entry path relative to root.
     * @param base base file
     * @param entry entry file
     * @return relative path
     */
    public static String getRelativePath(final File base, final File entry) {
        return entry.getAbsolutePath().substring(base.getAbsolutePath().length() + 1);
    }
}
